﻿using Devonline.AspNetCore;
using Devonline.Core;
using Microsoft.Extensions.Logging;

namespace Devonline.AuxiliaryTools.FileTools;

/// <summary>
/// json 文件操作相关的服务
/// </summary>
public class JsonFileService : DataFileService, IDataFileService, IFileService
{
    /// <summary>
    /// 构造方法
    /// </summary>
    /// <param name="logger">日志</param>
    /// <param name="httpSetting">Http配置项</param>
    public JsonFileService(ILogger<JsonFileService> logger, HttpSetting httpSetting) : base(logger, httpSetting) => _fileExtension = AppSettings.DEFAULT_CONFIG_FILE_EXTENSION;

    /// <summary>
    /// 写入数据到 Json 文件, 每个对象写一行, 此为大数据量写入处理方法
    /// </summary>
    /// <typeparam name="TEntitySet">写入的数据类型</typeparam>
    /// <param name="entitySets">写入的数据</param>
    /// <param name="fileName">文件名</param>
    /// <param name="converter">对象到数据行的转换方法, 传入参数分别是: 当前行字符串, 当前行号, 总行号</param>
    /// <returns>写入的总行数</returns>
    public override async Task<long> WriteAsync<TEntitySet>(IEnumerable<TEntitySet> entitySets, string? fileName = null, Func<TEntitySet, long, long, string?>? converter = null)
    {
        var index = 0L;
        if (!entitySets.Any())
        {
            return index;
        }

        var typeName = typeof(TEntitySet).GetDisplayName();
        var total = entitySets.LongCount();
        fileName = GetFileName<TEntitySet>(fileName);
        _logger.LogInformation($"将写入 {typeName} 数据 {total} 行到文件: {fileName} 中!");

        var line = string.Empty;
        using var writer = GetWriter(fileName);

        try
        {
            await writer.WriteLineAsync($"[");
            foreach (var entitySet in entitySets)
            {
                line = (converter ?? ConvertTo)(entitySet, index, total);
                if (!string.IsNullOrWhiteSpace(line))
                {
                    await writer.WriteLineAsync(line);
                }

                index++;
            }

            await writer.WriteLineAsync($"]");
            _logger.LogInformation($"已写入 {typeName} 数据 {index} 行到文件: {fileName} 中!");
        }
        catch (Exception ex)
        {
            throw new Exception($"写入 {typeName} 数据第 {index} 行到文件: {fileName} 发生异常, 错误对象: {line}", ex);
        }
        finally
        {
            await writer.FlushAsync();
            writer.Close();
        }

        return index;
    }

    /// <summary>
    /// 转换对象为字符串形式
    /// </summary>
    /// <typeparam name="TEntitySet">对象类型</typeparam>
    /// <param name="entitySet">对象值</param>
    /// <param name="index">当前行数</param>
    /// <param name="total">总行数</param>
    /// <returns>转换后的字符串格式</returns>
    protected override string? ConvertTo<TEntitySet>(TEntitySet entitySet, long index, long total)
    {
        var value = entitySet.ToJsonString();
        if (value is not null && (index + 1) != total)
        {
            value += AppSettings.DEFAULT_SPLITER_STRING;
        }

        return value;
    }
    /// <summary>
    /// 转换字符串为指定对象
    /// </summary>
    /// <typeparam name="TEntitySet">对象类型</typeparam>
    /// <param name="value">字符串值</param>
    /// <param name="index">当前行数</param>
    /// <returns>转换后的对象</returns>
    protected override TEntitySet? ConvertTo<TEntitySet>(string value, long index) where TEntitySet : class
    {
        if (value != "[" && value != "]")
        {
            if (value.EndsWith(AppSettings.DEFAULT_SPLITER_STRING))
            {
                value = value[..^AppSettings.UNIT_TWO];
            }

            return value.ToJsonObject<TEntitySet>();
        }

        return default;
    }
}